home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / apps / xconf / ConfRouter.c++ < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  260 lines

  1.  
  2. // Conf includefile
  3. #include "ConfRouter.h"
  4.  
  5. // unix includes
  6. #include <stdlib.h>
  7. #include <sys/socket.h>
  8. #include <sys/ioctl.h>
  9. #include <malloc.h>
  10. #include <ctype.h>
  11. #include <fcntl.h>
  12. #include <unistd.h>
  13. #include <bstring.h>
  14. #include <CC/osfcn.h>
  15. #include <netdb.h>
  16. #include <arpa/inet.h>
  17.  
  18.  
  19. ConfRouter::ConfRouter() {}
  20.  
  21.  
  22. ConfRouter::~ConfRouter() {}
  23.  
  24.  
  25. void ConfRouter::Init(int port)
  26. {  
  27.    _port = port;
  28.    _addrSize = sizeof(struct sockaddr_in);
  29.  
  30.    bzero(&_tcpSendAddr, _addrSize);
  31.    _tcpSendAddr.sin_family = AF_INET;
  32.    _tcpSendAddr.sin_port = htons(_port);
  33.    _tcpSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  34.  
  35.    bzero(&_tcpRecvAddr, _addrSize);
  36.    _tcpRecvAddr.sin_family = AF_INET;
  37.    _tcpRecvAddr.sin_port = htons(_port);
  38.    _tcpRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  39.  
  40.    bzero(&_udpSendAddr, _addrSize);
  41.    _udpSendAddr.sin_family = AF_INET;
  42.    _udpSendAddr.sin_port = htons(_port);
  43.    _udpSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  44.  
  45.    bzero(&_udpRecvAddr, _addrSize);
  46.    _udpRecvAddr.sin_family = AF_INET;
  47.    _udpRecvAddr.sin_port = htons(_port);
  48.    _udpRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  49.  
  50.    if(!setupTCP()) {
  51.       printf("Error setting up TCP socket.\n");
  52.       exit(-1);
  53.    }
  54.    if(!setupUDP()){
  55.       printf("Error setting up UDP socket.\n");
  56.       exit(-1);
  57.    }
  58. }
  59.  
  60.  
  61. Boolean ConfRouter::setupTCP()
  62. {
  63.    _tcpSocket = socket(AF_INET, SOCK_STREAM, 0);
  64.    if(_tcpSocket < 0) {
  65.       perror("socket");
  66.       return(FALSE);
  67.    }
  68.  
  69.    if(bind(_tcpSocket, &_tcpRecvAddr, _addrSize) < 0) {
  70.       perror("bind");
  71.       return(FALSE);
  72.    }
  73.  
  74.    if(listen(_tcpSocket, 5) < 0) {
  75.       perror("listen");
  76.       return(FALSE);
  77.    }
  78.  
  79.    if(fcntl(_tcpSocket, F_SETFL, FASYNC) < 0) {
  80.       perror("fcntl");
  81.       return(FALSE);
  82.    }
  83.  
  84.    if(fcntl(_tcpSocket, F_SETOWN, getpid()) < 0) {
  85.       perror("fcntl");
  86.       return(FALSE);
  87.    }
  88.  
  89.    return(TRUE);
  90. }
  91.  
  92.  
  93. Boolean ConfRouter::setupUDP()
  94. {
  95.    _udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
  96.    if(_udpSocket < 0) {
  97.       perror("socket");
  98.       return(FALSE);
  99.    }
  100.  
  101.    int on = 1;
  102.    // doing this before the bind allows multiple bindings to this port
  103.    if(setsockopt(_udpSocket, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) {
  104.       perror("setsockopt(SO_REUSEPORT)");
  105.       return(FALSE);
  106.    }
  107.  
  108.    struct in_addr grpAddr;
  109.    grpAddr.s_addr = inet_addr(XCONF_MCAST_GROUP);
  110.    if(!IN_MULTICAST(grpAddr.s_addr)) {
  111.       fprintf(stderr, "Invalid multicast group address.\n");
  112.       return(FALSE);
  113.    }
  114.  
  115.    // enable multicasting and limit # gateways packets will cross.
  116.    u_char ttl = MAX_MCAST_HOPS;
  117.    int sz = sizeof(ttl);
  118.    if(setsockopt(_udpSocket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sz) < 0) {
  119.       perror("setsockopt(IP_MULTICAST_TTL)");
  120.       return(FALSE);
  121.    }
  122.    _udpSendAddr.sin_addr = grpAddr;
  123.  
  124.    struct ip_mreq mreq;
  125.    mreq.imr_multiaddr = grpAddr;
  126.    struct in_addr ifAddr;
  127.    ifAddr.s_addr = htonl(INADDR_ANY);
  128.    mreq.imr_interface = ifAddr;
  129.    sz = sizeof(mreq);
  130.    if(setsockopt(_udpSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sz) < 0) {
  131.       perror("setsockopt(IP_ADD_MEMBERSHIP)");
  132.       return(FALSE);
  133.    }
  134.  
  135.    if(bind(_udpSocket, &_udpRecvAddr, _addrSize) < 0) {
  136.       perror("bind");
  137.       return(FALSE);
  138.    }
  139.  
  140.    if(fcntl(_udpSocket, F_SETFL, FASYNC) < 0) {
  141.       perror("fcntl(F_SETFL)");
  142.       return(FALSE);
  143.    }
  144.    if(fcntl(_udpSocket, F_SETOWN, getpid()) < 0) {
  145.       perror("fcntl(F_SETOWN)");
  146.       return(FALSE);
  147.    }
  148.  
  149.    return(TRUE);
  150. }
  151.  
  152.  
  153. Boolean ConfRouter::handleTCP()
  154. {
  155.    struct Message msg;
  156.    struct sockaddr_in f;
  157.    int fromlen = sizeof(f);
  158.  
  159.    if(recvfrom(_tcpSocket, &msg, sizeof(msg), 0, &f, &fromlen) < 0) {
  160.       perror("recv");
  161.       return(FALSE);
  162.    }
  163.  
  164.    printf("read TCP message.\n");
  165.  
  166.    int len = sizeof(msg) - sizeof(msg.data) + strlen(msg.data);
  167.  
  168.    if(sendto(_udpSocket, &msg, len, 0, &_udpSendAddr, _addrSize) < 0) {
  169.       perror("send");
  170.       return(FALSE);
  171.    }
  172.    bzero(msg.data, sizeof(msg.data));
  173.  
  174.    printf("sent UDP message.\n\n");
  175.    return(TRUE);
  176. }
  177.  
  178.  
  179. Boolean ConfRouter::handleUDP()
  180. {
  181.    struct Message msg;
  182.    struct sockaddr_in f;
  183.    int fromlen = sizeof(f);
  184.  
  185.    if(recvfrom(_udpSocket, &msg, sizeof(msg), 0, &f, &fromlen) < 0) {
  186.       perror("recvfrom");
  187.       return(FALSE);
  188.    }
  189.  
  190.    printf("read UDP message.\n");
  191.  
  192.    int len = sizeof(msg) - sizeof(msg.data) + strlen(msg.data);
  193.  
  194.    if(send(_tcpSocket, &msg, len, 0) < 0) {
  195.       perror("sendto");
  196.       return(FALSE);
  197.    }
  198.    bzero(msg.data, sizeof(msg.data));
  199.  
  200.    printf("sent TCP message.\n\n");
  201.    return(TRUE);
  202. }
  203.  
  204.  
  205. void ConfRouter::Run()
  206. {
  207.    int newsock;
  208.  
  209.    for(;;) {
  210.       newsock = accept(_tcpSocket, NULL, NULL);
  211.  
  212.  
  213. printf("new connection\n");
  214.  
  215.       if(!fork()) {
  216.          // child process
  217.          signal(SIGPOLL, SIG_IGN);
  218.  
  219.          close(_tcpSocket);
  220.          _tcpSocket = newsock;
  221.          int nfds = _tcpSocket + 1;
  222.  
  223.          fd_set readfds;
  224.          FD_ZERO(&readfds);
  225.  
  226.          for(;;) {
  227.             FD_SET(_tcpSocket, &readfds);
  228.             FD_SET(_udpSocket, &readfds);
  229.    
  230.             if(select(nfds, &readfds, (fd_set*)0, (fd_set*)0, (struct timeval*)0) < 0) {
  231.                perror("select");
  232.                exit(-1);
  233.             }
  234.  
  235. printf("select occured\n");
  236.  
  237.             if(FD_ISSET(_tcpSocket, &readfds)) {
  238.                handleTCP();
  239.             }
  240.             if(FD_ISSET(_udpSocket, &readfds)) {
  241.                handleUDP();
  242.             }
  243.          }
  244.       }
  245.       else {
  246.          // parent process
  247.          close(newsock);
  248.       }
  249.    }
  250. }
  251.  
  252.  
  253. void ConfRouter::Quit()
  254. {
  255.    close(_tcpSocket);
  256.    close(_udpSocket);
  257.    exit(1);
  258. }
  259.  
  260.